<?php
require_once 'Zend/Controller/Plugin/Abstract.php';
require_once 'Zend/Cache.php';
require_once 'Zend/Acl.php';
require_once 'Zend/Acl/Resource.php';
require_once 'Zend/Acl/Role.php';
require_once 'app/plugins/TTAcl.php';

class AclPlugin extends Zend_Controller_Plugin_Abstract {	
	
	/*Check the ACL from cache first of all, then fetching from the database*/
	public function dispatchLoopStartup(Zend_Controller_Request_Abstract $request) 
	{	
		$cache = Zend_Registry::get('cache');		
		$this->_db = Zend_Registry::get('db_adapter');		
		// Cache acl relationships
		if (!$acl = unserialize($cache->load('acl'))) 
		{				
			/*Initial the acl component*/
			$acl = new TTAcl();
			//select out the roles			
			$select = $this->_db->select();
			$select->from('tt_role', array ('id', 'name'));		
			try{	
				$roles = $this->_db->fetchAll($select);
			}catch(Exception $e){
				echo "Database is not set correctly!";
				exit;		
			}
			foreach ($roles as $role) {
				$acl->addRole(new Zend_Acl_Role($role['name']));
			}

			//select out the resources	
			$select = $this->_db->select();
			$select->from('tt_controller', array ('id', 'name'));
			$resources = $this->_db->fetchAll($select);
			foreach ($resources as $resource) {
				$acl->add(new Zend_Acl_Resource($resource['name']));
			}

			//select out the task privileges	
			$select = $this->_db->select();
			$select->from('tt_task_priv', array ('id', 'name'));
			$privileges = $this->_db->fetchAll($select);
			foreach ($privileges as $privilege) {
				$acl->add(new Zend_Acl_Resource($privilege['name']));
			}

			//select out the role resources relationships
			$sql = 'select rr.*, r.name as role, c.name as controller, a.name as act '
				 . 'from tt_rsh_role_resource rr, tt_role r, tt_controller c, tt_action a '
				 . 'where rr.tt_role_id=r.id and rr.tt_controller_id=c.id and rr.tt_action_id=a.id';	
			$res = $this->_db->query($sql);
			$RshRs = $res->fetchAll();
			$aclArray = array();
			foreach ($RshRs as $k => $CA) {
				$aclArray[$CA['role']][$CA['controller']][] = $CA['act'];
			}	
			//echo'<pre>';print_r($aclArray);echo'</pre>';exit;
			foreach ($aclArray as $acl_role => $acl_ca) {
				if (count($acl_ca) <= 0) {
					$acl->allow($acl_role); // hold all privileges
					continue;
				}
				foreach ($acl_ca as $acl_controller => $acl_actions) {
					if (count($acl_actions) > 0) {
						foreach ($acl_actions as $acl_action) {
							$acl->allow($acl_role, $acl_controller, $acl_action);
						}
					} else {
						$acl->allow($acl_role, $acl_controller);
					}
				}
			}

			//select out the role resources relationships
			$sql = 'select rtp.*, r.name as role, tp.name as name, tp.description as descript '
				 . 'from tt_rsh_role_task_priv rtp, tt_role r, tt_task_priv tp '
				 . 'where rtp.tt_role_id=r.id and rtp.task_priv_id=tp.id';
			$res = $this->_db->query($sql);
			$RshRs = $res->fetchAll();
			$aclArray = array();
			foreach ($RshRs as $k => $CA) {
				$aclArray[$CA['role']][] = $CA['name'];
			}	
			//echo'<pre>';print_r($aclArray);echo'</pre>';exit;
			foreach ($aclArray as $acl_role => $acl_ca) {
				if (sizeof($acl_ca) <= 0) continue;
				foreach ($acl_ca as $acl_key => $acl_privilege) {
					$acl->allow($acl_role, $acl_privilege);
				}
			}

			$cache->save(serialize($acl), 'acl');			
		}

		Zend_Registry::set("acl", $acl);
		
		// Cache actions must be judged by acl controller
		if (!$actions = unserialize($cache->load('act'))) {
	    	$actions = array();
	    	$data = $this->_db->fetchAll('select distinct name from tt_action');
	    	foreach ($data as $row) {
	    		array_push($actions, $row['name']);
	    	}
	    	$cache->save(serialize($actions), 'act');
		}
		
		Zend_Registry::set("act", $actions);
	}
	
	public function preDispatch(Zend_Controller_Request_Abstract $request)
	{
		if ($request->get('clearcache')=='all') {
			$cache = Zend_Registry::get('cache');
			$cache->clean(Zend_Cache::CLEANING_MODE_ALL);
		}
		$this->_acl = Zend_Registry::get('acl');
		$this->_act = Zend_Registry::get('act');

		try{
			$control	= $request->getControllerName();
			$action		= $request->getActionName();
			if($control != 'auth' && $control != 'index' && in_array($action, $this->_act)){
				// Page authentication
				$user = Zend_Auth::getInstance()->getIdentity();
				if ($user == null) {
					$this->_response->setRedirect('/auth/login');
					$this->_response->sendResponse();
				} else {			
					if(!$this->_acl->isAllowed(null, $control, $action)){					
						//todo permission deny
						$redirect_url = isset($_SERVER['HTTP_REFERER']) ? $_SERVER['HTTP_REFERER'] : __ROOT_HOST;
						echo '<script language="javascript">';
						echo 'alert("Access Deny!");';
						echo 'location.href = "'.$redirect_url.'";';
						echo '</script>';
						exit;
					}
				}	
			}
		}catch(Exception $e){
			//error occurred
		}
	}    
}